﻿using HCMS.CommonDtos;
using HCMS.Entities.OAuth2;
using HCMS.Extensions;
using HCMS.IServices.OAuth2;
using HCMS.Utils;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Newtonsoft.Json;

namespace HCMS.HttpApi.Site.Filter
{
    /// <summary>
    /// 全局 异常处理 过滤器
    /// </summary>
    public class GlobalExceptionFilter : IAsyncExceptionFilter
    {
        private readonly IHostEnvironment _hostEnvironment;
        private readonly IApiRequestLogsAppService apiRequestLogsAppService;

        public GlobalExceptionFilter(
            IHostEnvironment hostEnvironment,
            IApiRequestLogsAppService apiRequestLogsAppService)
        {
            _hostEnvironment = hostEnvironment;
            this.apiRequestLogsAppService = apiRequestLogsAppService;
        }

        /// <summary>
        /// 异常处理方法
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public async Task OnExceptionAsync(ExceptionContext context)
        {
            var exceptionInfo = context.Exception;

            #region Api 请求日志
            ApiRequestLogs? apiRequestLogs = null;
            var logs = context.HttpContext.Items["apiRequestLogs"].ToString("");
            if (!string.IsNullOrWhiteSpace(logs))
            {
                apiRequestLogs = JsonConvert.DeserializeObject<ApiRequestLogs>(logs) ?? new ApiRequestLogs();
                apiRequestLogs.EndTime = DateTime.Now;
                var differenTime = DateTimeUtil.DifferenTimespan(apiRequestLogs.StartTime, apiRequestLogs.EndTime);
                apiRequestLogs.ExecutionTime = differenTime.Milliseconds;
            }
            #endregion

            #region 自定义友好异常 处理
            if ((exceptionInfo is HCMS.Extensions.UserFriendlyException) ||
                (exceptionInfo is Volo.Abp.UserFriendlyException))
            {
                var jsonResult = new JsonResult(
                    new AjaxResultDto() { Code = 500, Message = exceptionInfo.Message }
                );
                context.Result = jsonResult;

                #region 记录 Api 请求日志【结束】
                // 方法抛出友好异常：系统在这里记录 请求日志
                // 方法正常执行并返回：系统在【结果 执行 过滤器】记录 请求日志
                if (apiRequestLogs != null)
                {
                    apiRequestLogs.ResultInfo = $"请求失败。系统返回提示：{exceptionInfo.Message}";
                    await apiRequestLogsAppService.BaseInsertAsync(apiRequestLogs);
                }
                #endregion
            }
            #endregion

            #region 其它系统异常 处理
            else
            {
                // 记录异常日志
                var errorMsg = new List<string> {
                    "系统全局异常"
                };

                #region 同时记录 Api 请求日志
                if (apiRequestLogs != null)
                {
                    apiRequestLogs.ResultInfo = "";
                    errorMsg.Add(string.Format("请求参数：【{0}】", JsonConvert.SerializeObject(apiRequestLogs).Replace(",", ",\r\n")));
                }
                #endregion

                Log4NetUtil.Error(string.Join("\r\n", errorMsg), exceptionInfo, out string errorId);

                // 异常信息
                var messageContent = "";

                // 开发环境，显示具体异常信息
                if (_hostEnvironment.IsDevelopment())
                {
                    messageContent = exceptionInfo.ToString();
                }
                // 不是开发环境，显示友好消息
                else
                {
                    messageContent = $"发生了一个错误，错误Id[{errorId}]。我们已经记录了这个问题，并正在修复。";
                }

                var jsonResult = new JsonResult(
                    new AjaxResultDto() { Code = 500, Message = messageContent }
                );
                context.Result = jsonResult;
            }
            #endregion

            // 指示异常处理已经完成
            context.ExceptionHandled = true;
        }
    }
}
